using System;
using System.Collections.Generic;
using Tarkin.InfrastructureLibrary.Core.PrimitiveTypes;
using Tarkin.InfrastructureLibrary.Utilities.Collections;

namespace Tarkin.InfrastructureLibrary.Core.Basic
{
    /// <summary>
    /// The Operation class is the implementation of the Operation metaclass class as defined by 
    /// section 10.2.3 of the Unified Modeling Language: Infrastructure specfication (version 
    /// 2.1.1, dated 07-02-06).
    /// 
    /// NOTE - Due to C#'s single inheritance limitation, the Operation class leverages
    ///        containment to simulate inheriting from the TypedElement class.
    /// </summary>
    /// <remarks>Tarkin classes are NOT thread-safe.</remarks>
    public class Operation : MultiplicityElement
    {

#region Private Members

        /// <summary>
        /// Contained TypedElement instance.
        /// </summary>
        private TypedElement typedElement = null;

        /// <summary>
        /// The Parameters of the Operation.
        /// </summary>
        private List < Parameter > ownedParameters = null;

        /// <summary>
        /// The exceptions that are decliared as possible during an invocation of the operation.
        /// </summary>
        private Set < Type > raisedExceptions = null;

        /// <summary>
        /// The class that owns the Operation. 
        /// 
        /// NOTE - The UML: Infrastructure spec has this property named "class" which is a C# keyword.
        /// </summary>
        private Class owningClass = null;

#endregion


#region Private Properties

        /// <summary>
        /// Contained TypedElement instance.
        /// </summary>
        private TypedElement TypedElement
        {
            get
            {
                return typedElement;
            }

            set
            {
                if ( value == null )
                {
                    throw new ArgumentNullException ( "Typed Element cannont be null." );
                }

                typedElement = value;
            }
        }

#endregion


#region Constructors

        /// <summary>
        /// Overloaded constructor.
        /// </summary>
        /// <param name="typedElement">The TypedElement portion of the Operation class.</param>
        public Operation ( TypedElement typedElement )
        {
            TypedElement = typedElement;
        }

        /// <summary>
        /// Overloaded constructor.
        /// </summary>
        /// <param name="typedElement">The TypedElement portion of the Operation class.</param>
        /// <param name="multiplicityElement">The MultiplicityElement of the Operation class.</param>
        public Operation ( TypedElement typedElement,
                           MultiplicityElement multiplicityElement ) : base ( multiplicityElement )

        {
            TypedElement = typedElement;
        }

        /// <summary>
        /// Overloaded constructor.
        /// </summary>
        /// <param name="typedElement">The TypedElement portion of the Operation class.</param>
        /// <param name="isOrdered">Whether the MultiplicityElement is ordered or not.</param>
        /// <param name="isUnique">Whether the MultiplicityElement is unique or not.</param>
        /// <param name="lower">The lower value of the MultiplicityElement.</param>
        /// <param name="upper">The upper value of the MultiplicityElement.</param>
        public Operation ( TypedElement typedElement,
                           bool isOrdered,
                           bool isUnique,
                           uint lower,
                           UnlimitedNatural upper ) : base ( isOrdered,
                                                             isUnique,
                                                             lower,
                                                             upper )
        {
            TypedElement = typedElement;
        }

        /// <summary>
        /// Overloaded cosntructor.
        /// </summary>
        /// <param name="typedElement">The TypedElement portion of the Operation class.</param>
        /// <param name="multiplicityElement">The MultiplicityElement of the Operation class.</param>
        /// <param name="owningClass">The class that owns the Operation.
        /// 
        ///NOTE - The UML: Infrastructure spec has this property named "class" which is a C# keyword.</param>
        public Operation ( TypedElement typedElement,
                           MultiplicityElement multiplicityElement,
                           Class owningClass ) : base ( multiplicityElement )
        {
            TypedElement = typedElement;
            Class = owningClass;
        }

        /// <summary>
        /// Overloaded constructor.
        /// </summary>
        /// <param name="typedElement">The TypedElement portion of the Parameter class.</param>
        /// <param name="isOrdered">Whether the MultiplicityElement is ordered or not.</param>
        /// <param name="isUnique">Whether the MultiplicityElement is unique or not.</param>
        /// <param name="lower">The lower value of the MultiplicityElement.</param>
        /// <param name="upper">The upper value of the MultiplicityElement.</param>
        /// <param name="owningClass">The class that owns the Operation.
        /// 
        ///NOTE - The UML: Infrastructure spec has this property named "class" which is a C# keyword.</param>
        public Operation ( TypedElement typedElement,
                           bool isOrdered,
                           bool isUnique,
                           uint lower,
                           UnlimitedNatural upper,
                           Class owningClass ) : base ( isOrdered,
                                                        isUnique,
                                                        lower,
                                                        upper )
        {
            TypedElement = typedElement;
            Class = owningClass;
        }

#endregion


#region Public Properties

        /// <summary>
        /// The Type of the Parameter.
        /// </summary>
        public Type Type
        {
            get
            {
                return TypedElement.Type;
            }

            set
            {
                TypedElement.Type = value;
            }
        }

        /// <summary>
        /// The name of the Parameter.
        /// </summary>
        public string Name
        {
            get
            {
                return TypedElement.Name;
            }

            set
            {
                TypedElement.Name = value;
            }
        }

        /// <summary>
        /// The Parameters of the Operation.
        /// </summary>
        public IList < Parameter > OwnedParameters
        {
            get
            {
                if ( ownedParameters == null )
                {
                    ownedParameters = new List < Parameter > ();
                }

                return ownedParameters;
            }
        }

        /// <summary>
        /// The exceptions that are declared as possible during an invocation of the operation.
        /// </summary>
        public Set < Type > RaisedExceptions
        {
            get
            {
                if ( raisedExceptions == null )
                {
                    raisedExceptions = new Set < Type > ();
                }

                return raisedExceptions;
            }
        }

        /// <summary>
        /// The Class that owns the Operation.
        /// </summary>
        public Class Class
        {
            get
            {
                return owningClass;
            }

            set
            {
                owningClass = value;
            }
        }

#endregion

    }
}
